// MulticastChat.cpp
#include "MulticastChat.h"

MulticastChat::MulticastChat()
{
    // 初始化 Winsock
    WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
        printf("WSAStartup() 失败\n");
        exit(EXIT_FAILURE);
    }

    // 创建套接字
    if ((sock = WSASocket(AF_INET, SOCK_DGRAM, 0, NULL, 0,
                          WSA_FLAG_MULTIPOINT_C_LEAF | WSA_FLAG_MULTIPOINT_D_LEAF |
                              WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET) {
        printf("创建套接字失败: %d\n", WSAGetLastError());
        WSACleanup();
        exit(EXIT_FAILURE);
    }
}

MulticastChat::~MulticastChat()
{
    stopChat();
    closesocket(sock);
    WSACleanup();
}

bool MulticastChat::startChat()
{
    local.sin_family = AF_INET;
    local.sin_port = htons(5150);
    local.sin_addr.s_addr = INADDR_ANY;

    // 允许地址复用
    int enable = 1;
    if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&enable, sizeof(int)) < 0) {
        printf("setsockopt(SO_REUSEADDR) 失败:%d\n", WSAGetLastError());
        return false;
    }

    if (bind(sock, (struct sockaddr*)&local, sizeof(local)) == SOCKET_ERROR) {
        printf("绑定失败: %d\n", WSAGetLastError());
        return false;
    }


    remote.sin_family = AF_INET;
    remote.sin_port = htons(5150);
    remote.sin_addr.s_addr = inet_addr("233.0.0.1");

    // 加入多播组
    struct ip_mreq mreq;
    mreq.imr_multiaddr.s_addr = inet_addr("233.0.0.1");
    mreq.imr_interface.s_addr = INADDR_ANY;
    if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&mreq, sizeof(mreq)) == SOCKET_ERROR) {
        printf("setsockopt(IP_ADD_MEMBERSHIP) 失败:%d\n", WSAGetLastError());
        return false;
    }

    // 启动接收线程
    receiverThread = std::thread(&MulticastChat::receiveMessages, this);



    return true;
}

//void MulticastChat::sendMessage(const QString& message)
//{
//    if (sendto(sock, message.toUtf8().data(), message.length(), 0, (struct sockaddr*)&remote, sizeof(remote)) == SOCKET_ERROR) {
//        printf("sendto 失败: %d\n", WSAGetLastError());
//    }
//}
void MulticastChat::sendMessage(const QString& message)
{
    // 将 QString 转换为 QByteArray，使用 UTF-8 编码
    QByteArray byteArray = message.toUtf8();

    if (sendto(sock, byteArray.data(), byteArray.length(), 0, (struct sockaddr*)&remote, sizeof(remote)) == SOCKET_ERROR) {
        printf("sendto 失败: %d\n", WSAGetLastError());
    }
}

void MulticastChat::stopChat()
{
    // 发送离开消息
    sendMessage("LEAVE");

    // 停止接收线程
    receiverThread.join();
}

void MulticastChat::receiveMessages()
{
    struct sockaddr_in from;
    int len = sizeof(struct sockaddr_in);
    char buf[1024];
    int ret;

    while (1) {
        if ((ret = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr*)&from, &len)) == SOCKET_ERROR) {
            printf("recvfrom 失败: %d\n", WSAGetLastError());
            break;
        }

        buf[ret] = '\0';
        // 发射信号，通知接收到新消息
        emit recvData(QString::fromUtf8(buf));
    }
}
void MulticastChat::run()
{
    // 在这里放置线程执行的代码
    while (1) {
        // 处理接收消息的逻辑
        // 例如，你可以调用 receiveMessages() 函数
        receiveMessages();
    }
}
